package com.aco.fatureapp.printer.libs;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.UUID;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.os.SystemClock;

public class Bluetooth {
	public BluetoothAdapter adapter = null;
	public BluetoothSocket socket;
	public BluetoothDevice device;
	public InputStream istream;
	public BufferedOutputStream ostream;
	private static final UUID BLUETOOTH_SPP_UUID = UUID
			.fromString("00001101-0000-1000-8000-00805f9b34fb");

	public boolean isConnected() {
		return (socket != null && socket.isConnected());
	}

	public boolean Enable() {
		adapter = BluetoothAdapter.getDefaultAdapter();
		if (adapter != null) {
			if (adapter.isEnabled()) {
				return true;
			}
			adapter.enable();
			try {
				Thread.sleep(5000, 0);
			}
			catch (InterruptedException e) {
				e.printStackTrace();
			}
			;
			adapter = BluetoothAdapter.getDefaultAdapter();
			if (adapter.isEnabled()) {
				return true;
			}
		}
		return false;
	}

	public boolean Disable() {
		if (adapter != null) {
			if (adapter.isEnabled()) {
				adapter.disable();
			}
			if (!adapter.isEnabled()) {
				return true;
			}
		}
		return false;
	}

	public Set<BluetoothDevice> GetBondedDevices() {
		return adapter.getBondedDevices();
	}

	public boolean connectPrinter(String macAddress) throws Exception {
		try {
			if (socket == null || !socket.isConnected()) {
				connect(macAddress);
				return true;
			}
		}
		catch (IOException e) {
			SystemClock.sleep(2000);
			try {
				// Tentando conectar novamente
				socket = null;
				connect(macAddress);
				return true;
			}
			catch (Exception e2) {
				throw new Exception("Não foi possível conectar na impressora!");
			}

		}
		catch (Exception ex) {
			throw new IllegalAccessError(
					"Não foi possível conectar na impressora!");
		}

		return false;
	}

	public boolean Open(String mac) {
		try {
			this.Close();

			SystemClock.sleep(1000);

			adapter = BluetoothAdapter.getDefaultAdapter();

			device = adapter.getRemoteDevice(mac);

			adapter.cancelDiscovery();
			socket = device
					.createRfcommSocketToServiceRecord(BLUETOOTH_SPP_UUID);
			socket.connect();
			istream = socket.getInputStream();
			ostream = new BufferedOutputStream(socket.getOutputStream());

			SystemClock.sleep(1000);

			return true;
		}
		catch (IOException e) {
			return false;
		}
	}

	public void connect(String macAddress) throws Exception {
		try {
			// Pegando o adaptador bluetooth padrão
			BluetoothAdapter bluetoothDevice = BluetoothAdapter
					.getDefaultAdapter();

			// Buscando o mac adress da impressora
			device = bluetoothDevice.getRemoteDevice(macAddress);

			// Cancelando qualquer busca por novos dispositivos
			bluetoothDevice.cancelDiscovery();

			// Conexão insegura
			Method m;
			m = device.getClass().getMethod("createInsecureRfcommSocket",
					new Class[] { int.class });

			// Criando instância para a variável de instância socket
			socket = (BluetoothSocket) m.invoke(device, 1);
			socket.connect();

			SystemClock.sleep(1000);

			istream = socket.getInputStream();
			ostream = new BufferedOutputStream(socket.getOutputStream());
		}
		catch (Exception e) {
			throw e;
		}

	}

	public boolean Close() {
		try {
			if (ostream != null) {
				ostream.flush();
			}
			if (socket != null) {
				socket.close();
			}
			socket = null;
		}
		catch (IOException e) {
			return false;
		}
		return true;
	}

	public boolean Write(byte[] buffer, int count) {
		try {
			ostream.write(buffer, 0, count);
		}
		catch (IOException e) {
			return false;
		}
		return true;
	}

	public boolean Read(byte[] buffer, int length) {
		try {
			istream.read(buffer, 0, length);
		}
		catch (IOException e) {
			return false;
		}
		return true;
	}
}
